{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Softmax Regression Example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 生成数据集， 看明白即可无需填写代码\n",
    "#### '<font color=\"blue\">+</font>' 从高斯分布采样 (X, Y) ~ N(3, 6, 1, 1, 0).<br>\n",
    "#### '<font color=\"green\">o</font>' 从高斯分布采样  (X, Y) ~ N(6, 3, 1, 1, 0)<br>\n",
    "#### '<font color=\"red\">*</font>' 从高斯分布采样  (X, Y) ~ N(7, 7, 1, 1, 0)<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from matplotlib import animation, rc\n",
    "from IPython.display import HTML\n",
    "import matplotlib.cm as cm\n",
    "import numpy as np\n",
    "%matplotlib inline\n",
    "\n",
    "dot_num = 100\n",
    "x_p = np.random.normal(3., 1, dot_num)\n",
    "y_p = np.random.normal(6., 1, dot_num)\n",
    "y = np.ones(dot_num)\n",
    "C1 = np.array([x_p, y_p, y]).T\n",
    "\n",
    "x_n = np.random.normal(6., 1, dot_num)\n",
    "y_n = np.random.normal(3., 1, dot_num)\n",
    "y = np.zeros(dot_num)\n",
    "C2 = np.array([x_n, y_n, y]).T\n",
    "\n",
    "x_b = np.random.normal(7., 1, dot_num)\n",
    "y_b = np.random.normal(7., 1, dot_num)\n",
    "y = np.ones(dot_num)*2\n",
    "C3 = np.array([x_b, y_b, y]).T\n",
    "\n",
    "plt.scatter(C1[:, 0], C1[:, 1], c='b', marker='+')\n",
    "plt.scatter(C2[:, 0], C2[:, 1], c='g', marker='o')\n",
    "plt.scatter(C3[:, 0], C3[:, 1], c='r', marker='*')\n",
    "\n",
    "data_set = np.concatenate((C1, C2, C3), axis=0)\n",
    "np.random.shuffle(data_set)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 建立模型\n",
    "建立模型类，定义loss函数，定义一步梯度下降过程函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "epsilon = 1e-12\n",
    "class SoftmaxRegression():\n",
    "    def __init__(self):\n",
    "        self.W = tf.Variable(shape=[2, 3], dtype=tf.float32, \n",
    "            initial_value=tf.random.uniform(shape=[2, 3], minval=-0.1, maxval=0.1))\n",
    "        self.b = tf.Variable(shape=[1, 3], dtype=tf.float32, initial_value=tf.zeros(shape=[1, 3]))\n",
    "        \n",
    "        self.trainable_variables = [self.W, self.b]\n",
    "\n",
    "    def __call__(self, inp):\n",
    "        print(inp)\n",
    "        print(self.W)\n",
    "        print(self.b)\n",
    "        logits = tf.matmul(inp, self.W) + self.b # shape(N, 3)\n",
    "        pred = tf.nn.softmax(logits)\n",
    "        return pred    \n",
    "\n",
    "def compute_loss(pred, label):\n",
    "    label = tf.one_hot(tf.cast(label, dtype=tf.int32), dtype=tf.float32, depth=3)\n",
    "    \n",
    "    losses = -tf.reduce_sum(label*tf.math.log(pred+epsilon), axis=1)\n",
    "#     losses = tf.nn.softmax_cross_entropy_with_logits(label, pred)\n",
    "    loss = tf.reduce_mean(losses)\n",
    "    \n",
    "    accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(label,axis=1), tf.argmax(pred, axis=1)), dtype=tf.float32))\n",
    "    return loss, accuracy\n",
    "\n",
    "def train_one_step(model, optimizer, x, y):\n",
    "    with tf.GradientTape() as tape:\n",
    "        pred = model(x)\n",
    "        loss, accuracy = compute_loss(pred, y)\n",
    "        \n",
    "    grads = tape.gradient(loss, model.trainable_variables)\n",
    "    optimizer.apply_gradients(zip(grads, model.trainable_variables))\n",
    "    return loss, accuracy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 实例化一个模型，进行训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[6.2748194 2.51047  ]\n",
      " [5.2580924 2.751959 ]\n",
      " [2.7498114 5.3788857]\n",
      " [6.089799  4.370361 ]\n",
      " [7.5901093 6.574284 ]\n",
      " [6.028407  7.3423886]\n",
      " [7.6048384 6.5034833]\n",
      " [5.7555513 1.2067422]\n",
      " [5.161868  2.8525367]\n",
      " [4.2663217 6.6629367]\n",
      " [3.2515996 6.2266254]\n",
      " [2.3662522 5.4526005]\n",
      " [3.0866566 6.830762 ]\n",
      " [8.016466  9.267006 ]\n",
      " [2.3941813 6.2807093]\n",
      " [7.3111978 5.370868 ]\n",
      " [9.481455  5.698512 ]\n",
      " [6.0636134 4.9190083]\n",
      " [6.473895  6.310222 ]\n",
      " [7.652494  4.8730865]\n",
      " [5.84257   2.8927863]\n",
      " [4.520165  4.255332 ]\n",
      " [8.073997  5.616462 ]\n",
      " [3.8103595 7.441208 ]\n",
      " [7.603935  5.51962  ]\n",
      " [4.7574353 3.131766 ]\n",
      " [5.9826255 5.761625 ]\n",
      " [7.5997853 5.766635 ]\n",
      " [2.1347241 4.881936 ]\n",
      " [6.7013645 2.9373698]\n",
      " [4.441045  3.206592 ]\n",
      " [6.272583  3.1402476]\n",
      " [4.5797954 4.668129 ]\n",
      " [1.8538352 6.1858664]\n",
      " [2.7765841 7.392564 ]\n",
      " [6.4174747 6.188292 ]\n",
      " [1.5023545 5.9301066]\n",
      " [3.4849503 4.3056383]\n",
      " [6.412846  2.6642525]\n",
      " [6.34504   7.7597303]\n",
      " [3.3681586 8.376762 ]\n",
      " [1.77685   5.553679 ]\n",
      " [5.872031  2.9011006]\n",
      " [6.4804497 3.175038 ]\n",
      " [6.142147  3.5737946]\n",
      " [9.085186  7.156215 ]\n",
      " [8.530346  7.1484914]\n",
      " [8.364099  6.4891796]\n",
      " [8.088741  3.0926416]\n",
      " [6.5182524 5.0124025]\n",
      " [4.757326  2.2269437]\n",
      " [8.412469  7.079313 ]\n",
      " [6.8660913 7.3878293]\n",
      " [7.281686  8.093135 ]\n",
      " [6.412413  7.114059 ]\n",
      " [7.343962  7.5357013]\n",
      " [5.8500447 7.7281466]\n",
      " [3.2351172 5.424753 ]\n",
      " [6.1037498 2.403302 ]\n",
      " [5.804145  7.6391497]\n",
      " [1.7895508 7.0269256]\n",
      " [3.7312791 5.826697 ]\n",
      " [7.894006  8.125221 ]\n",
      " [7.218377  5.448903 ]\n",
      " [8.78248   5.993955 ]\n",
      " [6.3024054 6.2443   ]\n",
      " [6.5322723 6.840628 ]\n",
      " [5.4635696 2.848752 ]\n",
      " [5.549633  3.8014152]\n",
      " [3.3428502 7.2061744]\n",
      " [2.57169   6.68584  ]\n",
      " [3.1274774 4.5421543]\n",
      " [6.8938656 7.269383 ]\n",
      " [6.7194824 3.8107636]\n",
      " [6.68051   8.004269 ]\n",
      " [5.249596  6.9238944]\n",
      " [7.1550784 5.7785344]\n",
      " [2.9382248 4.4839797]\n",
      " [2.3523448 5.3000355]\n",
      " [9.117065  6.389164 ]\n",
      " [7.719422  8.159014 ]\n",
      " [6.3320007 7.7008853]\n",
      " [3.583197  5.289219 ]\n",
      " [3.0529382 7.0734143]\n",
      " [4.2110405 5.039507 ]\n",
      " [6.170167  3.6675367]\n",
      " [6.0205183 3.2729897]\n",
      " [2.409138  6.4119296]\n",
      " [6.8441997 6.1213737]\n",
      " [3.4185307 5.0804596]\n",
      " [4.9974585 2.9821289]\n",
      " [6.984343  6.823274 ]\n",
      " [6.4605002 1.4763658]\n",
      " [6.0742493 4.3490906]\n",
      " [1.3243006 6.203649 ]\n",
      " [6.3888445 2.5950022]\n",
      " [7.3108993 7.922461 ]\n",
      " [7.703175  6.5519814]\n",
      " [6.232168  8.443712 ]\n",
      " [8.142431  8.990278 ]\n",
      " [2.5820951 5.925618 ]\n",
      " [2.0586183 5.6007066]\n",
      " [2.0914173 5.2868023]\n",
      " [6.98547   6.064514 ]\n",
      " [7.816983  8.412275 ]\n",
      " [1.7566867 6.071051 ]\n",
      " [6.8408003 5.160108 ]\n",
      " [4.0336227 6.732021 ]\n",
      " [5.152741  1.9315829]\n",
      " [7.3019366 6.260281 ]\n",
      " [2.6320825 4.8447733]\n",
      " [3.306472  5.699172 ]\n",
      " [6.5873966 4.0957417]\n",
      " [3.8533933 1.8135905]\n",
      " [2.7239144 7.33743  ]\n",
      " [5.7230406 5.8624473]\n",
      " [7.3233376 7.1241026]\n",
      " [4.9201202 3.6594136]\n",
      " [4.8856244 1.9835494]\n",
      " [2.639293  8.578127 ]\n",
      " [2.8147628 7.154383 ]\n",
      " [7.127416  0.9460986]\n",
      " [5.132366  5.5258613]\n",
      " [4.8681297 3.1217158]\n",
      " [7.4518666 5.1779065]\n",
      " [7.18067   1.48339  ]\n",
      " [3.658149  5.551167 ]\n",
      " [7.867399  7.980631 ]\n",
      " [5.9912686 3.622941 ]\n",
      " [7.132693  9.869324 ]\n",
      " [6.3940825 4.456198 ]\n",
      " [5.373283  1.0053052]\n",
      " [5.167079  3.8046386]\n",
      " [2.4703991 4.7153716]\n",
      " [7.281475  7.0710516]\n",
      " [6.9528494 7.678557 ]\n",
      " [6.3760257 2.4855359]\n",
      " [6.5542555 3.4998987]\n",
      " [3.3547392 4.231018 ]\n",
      " [7.2044964 5.067116 ]\n",
      " [7.1531615 2.555187 ]\n",
      " [2.4725866 6.3531404]\n",
      " [5.698953  3.8684356]\n",
      " [3.8228853 5.420175 ]\n",
      " [6.5865507 3.2798352]\n",
      " [4.445481  2.2690115]\n",
      " [4.3916445 1.8052452]\n",
      " [8.287405  2.6596959]\n",
      " [7.1409626 1.3878744]\n",
      " [7.992951  7.1848636]\n",
      " [2.5160768 5.9146194]\n",
      " [4.087129  6.4615707]\n",
      " [3.5555909 6.5839276]\n",
      " [5.891884  5.3947215]\n",
      " [5.8632116 6.7555366]\n",
      " [3.608054  4.791472 ]\n",
      " [4.152612  5.88435  ]\n",
      " [7.9873195 6.825885 ]\n",
      " [6.637004  8.877562 ]\n",
      " [6.405527  7.018552 ]\n",
      " [1.8484293 4.8761973]\n",
      " [5.684555  2.4069982]\n",
      " [5.683271  2.9308794]\n",
      " [4.8711815 7.3514104]\n",
      " [5.893675  6.796134 ]\n",
      " [5.9493637 4.761277 ]\n",
      " [1.2067904 6.7418017]\n",
      " [5.5643067 7.259452 ]\n",
      " [5.273755  3.8069773]\n",
      " [7.4449615 6.2996464]\n",
      " [6.5316815 6.2054443]\n",
      " [8.725592  7.1186323]\n",
      " [6.594698  6.2550545]\n",
      " [6.137051  7.6585355]\n",
      " [5.8319616 7.9427714]\n",
      " [5.5592628 1.9119934]\n",
      " [3.4743867 6.017304 ]\n",
      " [5.2763934 1.8054626]\n",
      " [7.0517755 3.332601 ]\n",
      " [2.4432745 7.538959 ]\n",
      " [6.765199  3.9010396]\n",
      " [6.2613444 7.177444 ]\n",
      " [4.2365065 6.342538 ]\n",
      " [2.638675  7.0294375]\n",
      " [7.913171  6.666101 ]\n",
      " [5.8709764 1.2961165]\n",
      " [2.443388  5.172471 ]\n",
      " [6.3567815 3.868599 ]\n",
      " [5.72953   3.696528 ]\n",
      " [8.438482  2.4843807]\n",
      " [7.18509   7.697278 ]\n",
      " [6.3207603 9.677222 ]\n",
      " [7.044686  2.5418222]\n",
      " [3.1034768 4.395927 ]\n",
      " [6.273294  2.589108 ]\n",
      " [3.6202023 5.5314994]\n",
      " [5.614834  1.8588954]\n",
      " [3.7314672 6.3288493]\n",
      " [6.5628824 4.6013374]\n",
      " [6.2393594 2.611556 ]\n",
      " [5.251138  4.4742484]\n",
      " [6.0687547 1.9341044]\n",
      " [2.2951465 5.706024 ]\n",
      " [4.486366  5.820633 ]\n",
      " [5.391444  2.7485232]\n",
      " [8.138241  8.59728  ]\n",
      " [2.064105  4.767603 ]\n",
      " [3.8966446 5.462834 ]\n",
      " [2.0858915 7.135935 ]\n",
      " [7.7474823 7.378451 ]\n",
      " [4.1546793 7.162185 ]\n",
      " [2.5685802 5.578954 ]\n",
      " [4.5719757 4.586485 ]\n",
      " [6.1691    2.0730112]\n",
      " [2.1601021 6.7872148]\n",
      " [6.199668  3.7589238]\n",
      " [6.9381723 7.8834333]\n",
      " [2.6359892 4.230637 ]\n",
      " [3.5370026 6.760554 ]\n",
      " [6.678377  6.438816 ]\n",
      " [7.797625  6.1153245]\n",
      " [7.219946  2.9196877]\n",
      " [4.4208255 6.5567327]\n",
      " [1.9885565 6.815642 ]\n",
      " [7.244087  8.319691 ]\n",
      " [7.764329  6.936338 ]\n",
      " [7.769478  6.817905 ]\n",
      " [4.337635  3.8800244]\n",
      " [1.4651955 5.3099976]\n",
      " [6.6219645 3.7307122]\n",
      " [6.938503  6.8062263]\n",
      " [4.1097426 6.638015 ]\n",
      " [5.515163  5.3280454]\n",
      " [2.5399158 6.4383483]\n",
      " [6.2422495 4.5900397]\n",
      " [8.122062  5.9292493]\n",
      " [2.8892848 7.2448945]\n",
      " [5.8075156 2.8893404]\n",
      " [5.6434736 2.1231556]\n",
      " [5.622367  0.6806505]\n",
      " [3.8663628 5.120973 ]\n",
      " [5.916628  4.4268847]\n",
      " [1.7219065 5.951384 ]\n",
      " [2.495482  5.3245406]\n",
      " [2.582119  7.1928544]\n",
      " [5.5829024 6.7615614]\n",
      " [6.7289567 8.317221 ]\n",
      " [2.74311   4.9169483]\n",
      " [6.6435432 1.5540318]\n",
      " [7.0788364 2.1861665]\n",
      " [5.086048  2.652682 ]\n",
      " [2.4567065 4.526682 ]\n",
      " [4.571616  1.7470514]\n",
      " [3.7143269 4.254001 ]\n",
      " [7.751751  6.3557115]\n",
      " [6.7232604 6.434676 ]\n",
      " [7.353052  2.0769598]\n",
      " [2.9932525 4.3175273]\n",
      " [8.012585  5.3793225]\n",
      " [6.2985673 2.9328   ]\n",
      " [3.3704696 6.4682236]\n",
      " [2.6234918 4.841783 ]\n",
      " [7.0652256 2.7628965]\n",
      " [6.932658  3.3117476]\n",
      " [6.7313046 4.8971057]\n",
      " [7.1146297 6.397391 ]\n",
      " [7.333592  6.914992 ]\n",
      " [3.4223819 5.2161922]\n",
      " [7.639523  1.2443084]\n",
      " [7.743435  5.922342 ]\n",
      " [6.452987  2.504013 ]\n",
      " [4.5916476 1.6065416]\n",
      " [6.477741  7.9256644]\n",
      " [6.414591  2.8423364]\n",
      " [2.745341  4.9956994]\n",
      " [7.1910887 6.6868486]\n",
      " [3.2358642 5.0632396]\n",
      " [3.7192414 6.907961 ]\n",
      " [6.998982  8.102449 ]\n",
      " [6.9260106 6.5542717]\n",
      " [7.577897  7.729591 ]\n",
      " [4.9787083 2.0586894]\n",
      " [2.988718  6.8373017]\n",
      " [4.5655966 4.845236 ]\n",
      " [5.428615  5.635781 ]\n",
      " [2.6135662 5.732978 ]\n",
      " [3.1728878 5.2606463]\n",
      " [6.084864  8.05281  ]\n",
      " [6.37634   4.261068 ]\n",
      " [7.275164  7.4243135]\n",
      " [8.383683  2.726786 ]\n",
      " [5.8543153 3.1918252]\n",
      " [5.0338254 2.3791547]\n",
      " [2.8052373 5.407958 ]\n",
      " [8.328024  6.358348 ]\n",
      " [2.4312158 6.8874354]\n",
      " [7.1048107 2.6985416]\n",
      " [6.901141  6.4665217]\n",
      " [4.9862404 2.7379568]\n",
      " [6.0153975 6.5824447]], shape=(300, 2), dtype=float32)\n",
      "<tf.Variable 'Variable:0' shape=[2, 3] dtype=float32, numpy=\n",
      "array([[-0.03564847,  0.03899076, -0.05302269],\n",
      "       [ 0.02528689,  0.06625014,  0.0926649 ]], dtype=float32)>\n",
      "<tf.Variable 'Variable:0' shape=[1, 3] dtype=float32, numpy=array([[0., 0., 0.]], dtype=float32)>\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'list' object has no attribute 'ndims'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-20-734c7ec530af>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1000\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m     \u001b[0mloss\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maccuracy\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtrain_one_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mopt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconstant\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfloat32\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconstant\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfloat32\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      7\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m%\u001b[0m\u001b[0;36m50\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;36m49\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      8\u001b[0m         \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf'loss: {loss.numpy():.4}\\t accuracy: {accuracy.numpy():.4}'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-19-c00725813d2d>\u001b[0m in \u001b[0;36mtrain_one_step\u001b[0;34m(model, optimizer, x, y)\u001b[0m\n\u001b[1;32m     28\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mtrain_one_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptimizer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     29\u001b[0m     \u001b[0;32mwith\u001b[0m \u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGradientTape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mtape\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 30\u001b[0;31m         \u001b[0mpred\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     31\u001b[0m         \u001b[0mloss\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maccuracy\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcompute_loss\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpred\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     32\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-19-c00725813d2d>\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, inp)\u001b[0m\n\u001b[1;32m     12\u001b[0m         \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mW\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     13\u001b[0m         \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m         \u001b[0mlogits\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmatmul\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mW\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m+\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mb\u001b[0m \u001b[0;31m# shape(N, 3)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     15\u001b[0m         \u001b[0mpred\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msoftmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlogits\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     16\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mpred\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/a3/envs/tf2.0/lib/python3.7/site-packages/tensorflow/python/util/dispatch.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m    178\u001b[0m     \u001b[0;34m\"\"\"Call target, and fall back on dispatchers if there is a TypeError.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    179\u001b[0m     \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 180\u001b[0;31m       \u001b[0;32mreturn\u001b[0m \u001b[0mtarget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    181\u001b[0m     \u001b[0;32mexcept\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mTypeError\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    182\u001b[0m       \u001b[0;31m# Note: convert_to_eager_tensor currently raises a ValueError, not a\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/a3/envs/tf2.0/lib/python3.7/site-packages/tensorflow/python/ops/math_ops.py\u001b[0m in \u001b[0;36mmatmul\u001b[0;34m(a, b, transpose_a, transpose_b, adjoint_a, adjoint_b, a_is_sparse, b_is_sparse, name)\u001b[0m\n\u001b[1;32m   2584\u001b[0m     \u001b[0;31m# TODO(apassos) remove _shape_tuple here when it is not needed.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2585\u001b[0m     \u001b[0ma_shape\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_shape_tuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# pylint: disable=protected-access\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2586\u001b[0;31m     \u001b[0mb_shape\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_shape_tuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# pylint: disable=protected-access\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   2587\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2588\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mfwd_compat\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mforward_compatible\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2019\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m25\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/a3/envs/tf2.0/lib/python3.7/site-packages/tensorflow/python/ops/resource_variable_ops.py\u001b[0m in \u001b[0;36m_shape_tuple\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    829\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    830\u001b[0m   \u001b[0;32mdef\u001b[0m \u001b[0m_shape_tuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 831\u001b[0;31m     \u001b[0mshape\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_shape_as_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    832\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mshape\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    833\u001b[0m       \u001b[0;32mreturn\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/a3/envs/tf2.0/lib/python3.7/site-packages/tensorflow/python/ops/resource_variable_ops.py\u001b[0m in \u001b[0;36m_shape_as_list\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    824\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    825\u001b[0m   \u001b[0;32mdef\u001b[0m \u001b[0m_shape_as_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 826\u001b[0;31m     \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndims\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    827\u001b[0m       \u001b[0;32mreturn\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    828\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mdim\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalue\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mdim\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdims\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mAttributeError\u001b[0m: 'list' object has no attribute 'ndims'"
     ]
    }
   ],
   "source": [
    "model = SoftmaxRegression()\n",
    "opt = tf.keras.optimizers.SGD(learning_rate=0.01)\n",
    "x1, x2, y = list(zip(*data_set))\n",
    "x = list(zip(x1, x2))\n",
    "for i in range(1000):\n",
    "    loss, accuracy = train_one_step(model, opt, tf.constant(x, dtype=tf.float32), tf.constant(y, dtype=tf.float32))\n",
    "    if i%50==49:\n",
    "        print(f'loss: {loss.numpy():.4}\\t accuracy: {accuracy.numpy():.4}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 结果展示，无需填写代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 2)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(C1[:, 0], C1[:, 1], c='b', marker='+')\n",
    "plt.scatter(C2[:, 0], C2[:, 1], c='g', marker='o')\n",
    "plt.scatter(C3[:, 0], C3[:, 1], c='r', marker='*')\n",
    "\n",
    "x = np.arange(0., 10., 0.1)\n",
    "y = np.arange(0., 10., 0.1)\n",
    "\n",
    "X, Y = np.meshgrid(x, y)\n",
    "inp = np.array(list(zip(X.reshape(-1), Y.reshape(-1))), dtype=np.float32)\n",
    "print(inp.shape)\n",
    "Z = model(inp)\n",
    "Z = np.argmax(Z, axis=1)\n",
    "Z = Z.reshape(X.shape)\n",
    "plt.contour(X,Y,Z)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
